##
# AudienceStar comments
# This file contains handlers for adding comments or questions
##


# This defines all our data types that are stored in Google's database
from astarclasses import *
from google.appengine.api import urlfetch
from appengine_utilities import sessions
from google.appengine.api import channel
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.api import images
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from datetime import datetime
from string import Template
import string
from string import *
import cgi
import os
import logging
import sys
import time # to sleep
import re
from django.utils import simplejson as json


from astarutils import * # this defines helpful functions like friendly date delta format

class QuestionAnswered(webapp.RequestHandler):
	def post(self):
		question_key = self.request.get("question_key")
		if (question_key):
			question = CommentQuestion.get(question_key)
			if question:
				question.answered = True
				question.put()



class QuestionOrComment(webapp.RequestHandler):		
	def post(self):
		talk_key = self.request.get("talk_key")
		if talk_key:
			talk = Talk.get(talk_key)
		else:
			talk = None
		if talk:
			topic = talk.current_topic
			self.sess = sessions.Session() # get the unique session id to identify this client
			star = None # begin by assuming that no user (star) has been created for this session
			if self.sess.has_key("star_key"): # try to find a star associated with this session
				star = Star.get(self.sess["star_key"])
			if star:
				question_or_comment = lower(self.request.get("type"))
				comment_text = self.request.get("comment_text")
				award_text = None # if we detect an award criteria, this will be replaced by a string
				if len(comment_text) > 500:
					award_text = "Long Winded"
				# clamp comments at 500 characters max
				comment_text = comment_text[:500]
				length_before_naughty = len(comment_text)
				# check for "naughty words" in the comment and remove them
				comment_text = re.sub("shit|fuck|bloody|bastard|wanker|penis|cunt|bitch|cocksucker|blowhard|sucker|banger(?i)", "*", comment_text)
				length_after_naughty = len(comment_text) # see if any naughty words were stripped out
				if length_after_naughty < length_before_naughty:
					award_text = "Naughty Words"
				if re.match("drop table|insert into table|733t(?i)", comment_text):
					award_text = "HAXXOR"
					
				# replace angle brackets to prevent any sort of script injection
				comment_text = comment_text.replace("<", " (less than) ")
				comment_text = comment_text.replace(">", " (greater than) ")
				# count words and length of longest word
				words = comment_text.split(" ")
				num_words = len(words)
				longest_word_len = 0
				for word in words:
					if len(word) > longest_word_len: longest_word_len = len(word)
				if num_words <= 3:
					award_text = "Brevity"
				if longest_word_len > 15:
					award_text = "Long Words"
				if longest_word_len > 25:
					award_text = "Really Long Words"
				# count how many comments/questions this star has contributed
				questions_for_star = db.GqlQuery("SELECT __key__ FROM CommentQuestion WHERE ANCESTOR IS :1 AND star =:2 LIMIT 55", talk, star)
				star_question_count = 0
				for qfs_key in questions_for_star:
					star_question_count += 1
				if star_question_count == 5:
					award_text = "Participation"
				elif star_question_count == 10:
					award_text = "Frequent Contributor"
				elif star_question_count == 20:
					award_text = "Prolific Contributor"
				elif star_question_count == 30:
					award_text = "Insane Commenter"
				elif star_question_count == 40:
					award_text = "Comment Dominator"
				elif star_question_count > 50:
					self.response.out.write(json.dumps({'error':'Sorry, but 50 comments is quite enough from one person. Thanks for your enthusiasm, but please take a break.'}))
					return
				# count how many unaswered questions are currently enqued
				if (question_or_comment == "question"):
					unanswered_questions = db.GqlQuery("SELECT * FROM CommentQuestion WHERE type=:1 AND answered=:2 AND talk =:3 ORDER BY created_date", "question", False, talk)
					num_unaswered = 0
					star_has_pending_question = False;
					for uq in unanswered_questions:
						if uq.star.key() == star.key():
							star_has_pending_question = True
						num_unaswered += 1
					# if this user has another question pending not answered, or if there are
					# 10 or more unaswered questions, prevent this new one from going through
					if star_has_pending_question:
						self.response.out.write(json.dumps({'error':'Sorry, but you currently have another question queued which has not been answered yet. Please try again later.'}))
						return
					if num_unaswered >= 7:
						self.response.out.write(json.dumps({'error':'Sorry, but there are currently 7 other questions queued to be addressed.  I cannot take any more right now.  Please try again later.'}))
						return
				if (question_or_comment in ("question", "comment") and comment_text):
					cq = CommentQuestion(parent=talk, talk=talk, topic=topic, star=star, type=question_or_comment, text=comment_text)
					cq.put()
					# if any award was given, save it in this star's list of awards
					if award_text:
						try:
							previous_awards = star.awards
						except:
							star.put() # make sure star has latest schema
						if (award_text not in star.awards):
							star.awards.append(award_text)
							star.put()
					
					# If this was a question, then send an update message to all connected presenters
					if question_or_comment=="question":
						new_question = {'key':str(cq.key()), 
										'asker_name':star.display_name, 
										'question_text':comment_text}
						message = json.dumps({'message':'new_question', 'new_question':new_question})
					
						connected_presenters_query = db.GqlQuery("SELECT __key__ FROM Presenter WHERE ANCESTOR IS :1", talk)
						num_presenters=0
						for connected_presenter_key in connected_presenters_query:
							try:
								channel.send_message("presenter-"+str(connected_presenter_key.id()),message)
								num_presenters +=1
							except:
								pass
						# if the user got an award, tell them about it
						if award_text:
							award_message = "You received the '%s' award!" % award_text
							self.response.out.write(json.dumps({'award_message':award_message, 'award_type':award_text}))
						else: # otherwise just give them an indication that their question was saved
							if num_presenters == 0:
								ok_message = 'Question was saved but no presenters received the notification!'
							else:
								ok_message = 'Your question has been saved.'
							self.response.out.write(json.dumps({'success':'ok', 'message':ok_message}))
					else:
						if award_text:
							award_message = "You received the '%s' award!" % award_text
							self.response.out.write(json.dumps({'award_message':award_message, 'award_type':award_text}))
						else:
							self.response.out.write(json.dumps({'success':'ok', 'message':'Your comment has been saved.'}))
				else:
					self.response.out.write(json.dumps({'error':'Your question or comment was NOT saved due to a malformed message. type=%s comment_text=%s' % (question_or_comment, comment_text)}))
			else:
				self.response.out.write(json.dumps({'error':'Could not save comment or question because you have no current session. Try enabling cookies and refreshing the page.'}))
		else:
			self.response.out.write(json.dumps({'error':'Could not save comment or question because there is no presentation with that id.'}))

	
application = webapp.WSGIApplication([('/comment/add', QuestionOrComment),
									  ('/question/answered', QuestionAnswered),
					  ],
				     debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
